import { arrayMethods } from './arr'

export function observer(data) {
  // console.log(data)
  if (typeof data != 'object' || data == null) return data
  // 通过这个类来数据劫持
  return new Observer(data)
}

class Observer {
  constructor(value) {
    // console.log(value)
    // 给 value 定义一个属性 为了给对象数组添加对象用的
    Object.defineProperty(value, '__ob__', {
      enumerable: false, // 不可枚举的属性
      value: this
    })
    // 判断数据
    if (Array.isArray(value)) {
      value.__proto__ = arrayMethods
      // console.log('数组')
      this.observeArray(value) // 处理数组对象
    } else {
      // 遍历 劫持 对象
      this.walk(value)
    }
  }
  walk(data) {
    // console.log(data)
    let keys = Object.keys(data) // 拿到所有的 key

    // 开始遍历劫持所有属性
    for (let i = 0; i < keys.length; i++) {
      let key = keys[i]
      let value = data[key]
      // console.log(data, key, value)
      defineReactive(data, key, value)
      // console.log(data, key, value)
    }
  }
  observeArray(value) {
    for (let i = 0; i < value.length; i++) {
      observer(value[i])
    }
  }
}

// 对对象中的属性进行劫持
function defineReactive(data, key, value) {
  observer(value) // deep 劫持
  Object.defineProperty(data, key, {
    get() {
      // console.log('获取')
      return value
    },
    set(newValue) {
      // console.log('设置')
      if (newValue == value) return value
      observer(newValue) // 最新值继续劫持
      value = newValue
    }
  })
}
